// TTS错误处理和降级机制

/**
 * TTS错误类型枚举
 */
export const TtsErrorType = {
  NETWORK_ERROR: 'network_error',
  AUTH_ERROR: 'auth_error',
  QUOTA_ERROR: 'quota_error',
  TIMEOUT_ERROR: 'timeout_error',
  AUDIO_ERROR: 'audio_error',
  UNKNOWN_ERROR: 'unknown_error'
};

/**
 * TTS错误处理器
 */
export class TtsErrorHandler {
  constructor() {
    this.retryCount = 0;
    this.maxRetries = 3;
    this.retryDelay = 1000;
    this.errorHistory = [];
    this.maxErrorHistory = 50;
  }

  /**
   * 分析错误类型
   */
  analyzeError(error) {
    const message = error.message || error.toString();
    const code = error.code || error.status;

    // 网络错误
    if (message.includes('network') || message.includes('fetch') || 
        message.includes('connection') || code === 'NETWORK_ERROR') {
      return TtsErrorType.NETWORK_ERROR;
    }

    // 认证错误
    if (message.includes('auth') || message.includes('token') || 
        message.includes('unauthorized') || code === 401) {
      return TtsErrorType.AUTH_ERROR;
    }

    // 配额错误
    if (message.includes('quota') || message.includes('limit') || 
        message.includes('exceeded') || code === 429) {
      return TtsErrorType.QUOTA_ERROR;
    }

    // 超时错误
    if (message.includes('timeout') || message.includes('timed out') || 
        code === 'TIMEOUT_ERROR') {
      return TtsErrorType.TIMEOUT_ERROR;
    }

    // 音频错误
    if (message.includes('audio') || message.includes('decode') || 
        message.includes('playback')) {
      return TtsErrorType.AUDIO_ERROR;
    }

    return TtsErrorType.UNKNOWN_ERROR;
  }

  /**
   * 记录错误
   */
  recordError(error, context = {}) {
    const errorInfo = {
      timestamp: Date.now(),
      type: this.analyzeError(error),
      message: error.message || error.toString(),
      code: error.code || error.status,
      context,
      stack: error.stack
    };

    this.errorHistory.push(errorInfo);
    
    // 保持错误历史记录在限制范围内
    if (this.errorHistory.length > this.maxErrorHistory) {
      this.errorHistory.shift();
    }

    console.error('[TTS Error]', errorInfo);
    return errorInfo;
  }

  /**
   * 判断是否应该重试
   */
  shouldRetry(error) {
    const errorType = this.analyzeError(error);
    
    // 网络错误和超时错误可以重试
    if (errorType === TtsErrorType.NETWORK_ERROR || 
        errorType === TtsErrorType.TIMEOUT_ERROR) {
      return this.retryCount < this.maxRetries;
    }

    // 认证错误和配额错误不应该重试
    if (errorType === TtsErrorType.AUTH_ERROR || 
        errorType === TtsErrorType.QUOTA_ERROR) {
      return false;
    }

    // 其他错误根据重试次数决定
    return this.retryCount < this.maxRetries;
  }

  /**
   * 获取重试延迟时间
   */
  getRetryDelay() {
    // 指数退避策略
    return this.retryDelay * Math.pow(2, this.retryCount);
  }

  /**
   * 处理错误并决定下一步操作
   */
  handleError(error, context = {}) {
    const errorInfo = this.recordError(error, context);
    const errorType = errorInfo.type;

    // 根据错误类型决定处理策略
    switch (errorType) {
      case TtsErrorType.NETWORK_ERROR:
        return this.handleNetworkError(error, context);
      
      case TtsErrorType.AUTH_ERROR:
        return this.handleAuthError(error, context);
      
      case TtsErrorType.QUOTA_ERROR:
        return this.handleQuotaError(error, context);
      
      case TtsErrorType.TIMEOUT_ERROR:
        return this.handleTimeoutError(error, context);
      
      case TtsErrorType.AUDIO_ERROR:
        return this.handleAudioError(error, context);
      
      default:
        return this.handleUnknownError(error, context);
    }
  }

  /**
   * 处理网络错误
   */
  handleNetworkError(error, context) {
    if (this.shouldRetry(error)) {
      this.retryCount++;
      const delay = this.getRetryDelay();
      
      console.warn(`[TTS] 网络错误，${delay}ms后重试 (${this.retryCount}/${this.maxRetries})`);
      
      return {
        action: 'retry',
        delay,
        fallback: false
      };
    } else {
      console.error('[TTS] 网络错误，重试次数已达上限，降级到浏览器TTS');
      return {
        action: 'fallback',
        reason: 'network_error_max_retries',
        fallback: true
      };
    }
  }

  /**
   * 处理认证错误
   */
  handleAuthError(error, context) {
    console.error('[TTS] 认证错误，请检查配置');
    return {
      action: 'fallback',
      reason: 'auth_error',
      fallback: true,
      critical: true
    };
  }

  /**
   * 处理配额错误
   */
  handleQuotaError(error, context) {
    console.error('[TTS] 配额超限，降级到浏览器TTS');
    return {
      action: 'fallback',
      reason: 'quota_exceeded',
      fallback: true
    };
  }

  /**
   * 处理超时错误
   */
  handleTimeoutError(error, context) {
    if (this.shouldRetry(error)) {
      this.retryCount++;
      const delay = this.getRetryDelay();
      
      console.warn(`[TTS] 超时错误，${delay}ms后重试 (${this.retryCount}/${this.maxRetries})`);
      
      return {
        action: 'retry',
        delay,
        fallback: false
      };
    } else {
      console.error('[TTS] 超时错误，重试次数已达上限，降级到浏览器TTS');
      return {
        action: 'fallback',
        reason: 'timeout_error_max_retries',
        fallback: true
      };
    }
  }

  /**
   * 处理音频错误
   */
  handleAudioError(error, context) {
    console.error('[TTS] 音频错误，降级到浏览器TTS');
    return {
      action: 'fallback',
      reason: 'audio_error',
      fallback: true
    };
  }

  /**
   * 处理未知错误
   */
  handleUnknownError(error, context) {
    if (this.shouldRetry(error)) {
      this.retryCount++;
      const delay = this.getRetryDelay();
      
      console.warn(`[TTS] 未知错误，${delay}ms后重试 (${this.retryCount}/${this.maxRetries})`);
      
      return {
        action: 'retry',
        delay,
        fallback: false
      };
    } else {
      console.error('[TTS] 未知错误，重试次数已达上限，降级到浏览器TTS');
      return {
        action: 'fallback',
        reason: 'unknown_error_max_retries',
        fallback: true
      };
    }
  }

  /**
   * 重置重试计数
   */
  resetRetryCount() {
    this.retryCount = 0;
  }

  /**
   * 获取错误统计
   */
  getErrorStats() {
    const stats = {};
    this.errorHistory.forEach(error => {
      stats[error.type] = (stats[error.type] || 0) + 1;
    });
    return stats;
  }

  /**
   * 清除错误历史
   */
  clearErrorHistory() {
    this.errorHistory = [];
    this.retryCount = 0;
  }
}

/**
 * 全局错误处理器实例
 */
export const ttsErrorHandler = new TtsErrorHandler();

/**
 * 浏览器TTS降级实现
 */
export function fallbackToBrowserTts(text, options = {}) {
  if (!('speechSynthesis' in window)) {
    console.warn('[TTS] 浏览器不支持speechSynthesis');
    return Promise.reject(new Error('浏览器不支持语音合成'));
  }

  return new Promise((resolve, reject) => {
    try {
      // 取消当前播放
      window.speechSynthesis.cancel();

      const utterance = new SpeechSynthesisUtterance(text);
      
      // 设置语音参数
      utterance.lang = options.language || 'zh-CN';
      utterance.rate = options.speedRatio || 1.0;
      utterance.pitch = options.pitchRatio || 1.0;
      utterance.volume = options.volumeRatio || 1.0;

      // 尝试选择中文语音
      const voices = window.speechSynthesis.getVoices();
      const chineseVoice = voices.find(voice => 
        voice.lang.includes('zh') || voice.lang.includes('CN')
      );
      if (chineseVoice) {
        utterance.voice = chineseVoice;
      }

      utterance.onend = () => {
        console.log('[TTS] 浏览器TTS播放完成');
        resolve();
      };

      utterance.onerror = (event) => {
        console.error('[TTS] 浏览器TTS播放错误:', event.error);
        reject(new Error(`浏览器TTS错误: ${event.error}`));
      };

      console.log('[TTS] 使用浏览器TTS播放:', text);
      window.speechSynthesis.speak(utterance);

    } catch (error) {
      console.error('[TTS] 浏览器TTS初始化失败:', error);
      reject(error);
    }
  });
}

/**
 * 带错误处理的TTS播放函数
 */
export async function ttsPlayWithErrorHandling(ttsFunction, text, options = {}) {
  ttsErrorHandler.resetRetryCount();
  
  while (true) {
    try {
      const result = await ttsFunction(text, options);
      ttsErrorHandler.resetRetryCount();
      return result;
    } catch (error) {
      const errorAction = ttsErrorHandler.handleError(error, { text, options });
      
      if (errorAction.action === 'retry') {
        await new Promise(resolve => setTimeout(resolve, errorAction.delay));
        continue;
      } else if (errorAction.action === 'fallback') {
        if (errorAction.fallback) {
          try {
            return await fallbackToBrowserTts(text, options);
          } catch (fallbackError) {
            console.error('[TTS] 降级播放也失败:', fallbackError);
            throw new Error(`TTS播放失败: ${error.message}, 降级播放也失败: ${fallbackError.message}`);
          }
        } else {
          throw error;
        }
      } else {
        throw error;
      }
    }
  }
}
